package com.cw.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cw.common.api.ResultObject;
import com.cw.common.constant.Constants;
import com.cw.common.constant.Response;
import com.cw.config.service.impl.RedisServiceImpl;
import com.cw.entity.SysMenu;
import com.cw.entity.SysRoleMenu;
import com.cw.entity.SysUser;
import com.cw.request.SearchCondition;
import com.cw.service.ISysMenuService;
import com.cw.service.ISysRoleMenuService;
import com.cw.service.ISysUserRoleService;
import com.cw.service.ISysUserService;
import com.cw.util.UUIDUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* @author smq
* @since 2021-04-28
*/
@Api(tags = {"菜单表"})
@RestController
@RequestMapping("/sys-menu")

    public class SysMenuController {

    @Autowired
    private ISysMenuService sysMenuService;

    @Autowired
    private ISysUserRoleService sysUserRoleService;

    @Autowired
    private ISysRoleMenuService sysRoleMenuService;

    @Autowired
    private ISysUserService sysUserService;

    @Resource
    private RedisServiceImpl redisService;

    /**
     * 获取菜单树形结构
     *
     * @return
     */
    @ApiOperation(value = "获取权限菜单树形结构", notes = "获取权限菜单树形结构")
    @RequestMapping(value = "/getMenuTree", method = RequestMethod.GET)
    public ResultObject getMenuTree() {
        List<SysMenu> sysMenu = sysMenuService.getSysMenu(null, null, null, null,null);
        return ResultObject.successReturn(getChildNodes(Constants.menuParentId, sysMenu));
    }

    /**
     * 递归遍历返回菜单树
     *
     * @param id
     * @param list
     * @return
     * @author caochun
     */
    public static List<SysMenu> getChildNodes(String id, List<SysMenu> list) {

        List<SysMenu> childList = new ArrayList<>();
        //遍历所有菜单找到所有父节点
        for (int i = 0; i < list.size(); i++) {
            if (null != list.get(i).getParentId()) {
                if (id.equals(list.get(i).getParentId())) {
                    childList.add(list.get(i));
                    //已经确定的数据删除，不在遍历
                    list.remove(i);
                    i--;
                }
            }
        }

        //判断是否有子菜单
        if (null == childList || childList.size() == 0) {
            return null;
        }

        //遍历所有父节点菜单，找到对应的子菜单
        //递归
        for (SysMenu entity : childList) {
            entity.setChildNodes(getChildNodes(entity.getId(), list));
        }
        return childList;

    }

    /**
     * 获取角色对应的菜单
     *
     * @param roleId
     * @return
     */
    @ApiOperation(value = "获取角色对应的菜单", notes = "根据角色编号获取角色对应的菜单")
    @ApiImplicitParam(name = "roleId", value = "角色编号", required = true)
    @RequestMapping(value = "/getRoleMenu", method = RequestMethod.POST)
    public List<String> getUserMenu(@RequestParam String roleId) {
        //查询角色对应的菜单权限
        List<SysRoleMenu> sysRoleMenu = sysRoleMenuService.getSysRoleMenu(roleId);
        //菜单编号集合
        List<String> menuIds = new ArrayList<>();
        for (SysRoleMenu srm : sysRoleMenu) {
            menuIds.add(srm.getMenuId());
        }
        return menuIds;
    }

    /**
     * 修改角色对应的菜单
     *
     * @param param
     * @return
     */
    @ApiOperation(value = "修改角色对应的菜单", notes = "根据角色编号,菜单编号集合修改角色对应的菜单")
    @ApiImplicitParam(name = "param", value = "json(roleId,menuIds)", required = true, dataType = "Map<String, Object>")
    @RequestMapping(value = "/updateRoleMenu", method = RequestMethod.POST)
    public ResultObject updateRoleMenu(@RequestBody Map<String, Object> param) {
        //用户编码
        String roleId = param.get("roleId").toString();
        //菜单编码集合
        List<String> menuIds = (List<String>) param.get("menuIds");

        LambdaQueryWrapper<SysRoleMenu> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SysRoleMenu::getRoleId, roleId);

        //删除用户对应的所有菜单
        sysRoleMenuService.remove(lambdaQueryWrapper);
        //用户菜单集合
        List<SysRoleMenu> sysRoleMenus = new ArrayList<>();
        for (int i = 0; i < menuIds.size(); i++) {
            SysRoleMenu sysRoleMenu = new SysRoleMenu();
            sysRoleMenu.setId(UUIDUtil.uuid());
            sysRoleMenu.setMenuId(menuIds.get(i));
            sysRoleMenu.setRoleId(roleId);
            sysRoleMenus.add(sysRoleMenu);
        }

        if (CollectionUtils.isEmpty(sysRoleMenus) && sysRoleMenus.size() == 0) { return ResultObject.successReturn("操作成功!!"); }

        //重新插入用户对应菜单
        boolean insertSysRoleMenu = sysRoleMenuService.saveBatch(sysRoleMenus);
        if (insertSysRoleMenu) {
            return ResultObject.successReturn(Constants.success);
        } else {
            return ResultObject.errorReturn("插入新的菜单权限失败!!!");
        }

    }

    /**
     * 添加角色对应的菜单
     *
     * @param param
     * @return
     */
    @ApiOperation(value = "添加角色对应的菜单", notes = "添加角色对应的菜单")
    @ApiImplicitParam(name = "param", value = "json(roleId,menuIds)", required = true, dataType = "Map<String, Object>")
    @RequestMapping(value = "/addRoleMenu", method = RequestMethod.POST)
    public int addRoleMenu(@RequestBody Map<String, Object> param) {
        //用户编码
        String roleId = param.get("roleId").toString();
        //菜单编码集合
        List<String> menuIds = (List<String>) param.get("menuIds");
        //用户菜单集合
        List<SysRoleMenu> sysRoleMenus = new ArrayList<>();
        for (int i = 0; i < menuIds.size(); i++) {
            SysRoleMenu sysRoleMenu = new SysRoleMenu();
            sysRoleMenu.setMenuId(menuIds.get(i));
            sysRoleMenu.setRoleId(roleId);
            sysRoleMenus.add(sysRoleMenu);
        }

        int insertSysRoleMenu = sysRoleMenuService.insertSysRoleMenu(sysRoleMenus);
        if (insertSysRoleMenu > 0) {
            return Constants.success;
        } else {
            return Constants.fail;
        }
    }

    /**
     * 添加权限菜单
     *
     * @param sysMenu
     * @return
     */
    @ApiOperation(value = "新增菜单", notes = "新增菜单")
    @ApiImplicitParam(name = "sysMenu", value = "权限菜单对象", required = true, dataType = "SysMenu")
    @RequestMapping(value = "/insertMenu", method = RequestMethod.POST)
    public Response insertMenu(@RequestBody SysMenu sysMenu) {
        //判断菜单名称是否已存在
        List<SysMenu> name = sysMenuService.getSysMenu(null, sysMenu.getName(), null, null, null);
        //菜单名称已存在,添加失败
        if (null != name && name.size() > 0) {
            return new Response(500, "菜单名称已存在");
        }
//        //判断菜单编码是否已存在
//        List<SysMenu> code = sysMenuService.getSysMenu(null, null, sysMenu.getCode(), null, null);
//	    //编码已存在,添加失败
//	    if (null != code && code.size() > 0) {
//            return new Response(500, "编码已存在");
//        }
        sysMenu.setCreateTime(LocalDateTime.now());
        int insertSysMenu = sysMenuService.insertSysMenu(sysMenu);
        if (insertSysMenu > 0) {
            //删除redis中存的菜单信息
//            redisService.remove(RedisConstant.menu);
//            return new Response();
            return new Response(200, "新增菜单成功");
        } else {
            return new Response(500, "新增菜单失败");
        }
    }

    /**
     * 删除权限菜单
     *
     * @param menuId
     * @return
     */
    @ApiOperation(value = "删除菜单", notes = "删除菜单")
//    @ApiImplicitParam(name = "menuId", value = "菜单编号", required = true, dataType = "Integer", paramType = "query")
    @RequestMapping(value = "/deleteMenu", method = RequestMethod.GET)
    public Response deleteMenu(@RequestParam String menuId) {
        int insertSysMenu = sysMenuService.deleteSysMenu(menuId);
        if (insertSysMenu > 0) {
            //清理Redis缓存
//            redisService.delLike(RedisConstant.menu);
//            return new Response();
            return new Response(200, "删除成功");
        } else {
            return new Response(500, "删除失败");
        }
    }


    @ApiOperation(value = "查询菜单", notes = "查询菜单")
    @ApiImplicitParam(name = "searchCondition", value = "菜单查询条件", required = true, dataType = "SearchCondition")
    @RequestMapping(value = "/getMenu", method = RequestMethod.POST)
    public Response getMenu(@RequestBody SearchCondition searchCondition) {
        List<SysMenu> sysMenu = sysMenuService
                .getSysMenu(searchCondition.getMenuId(), null, null, null, null);
        if (null != sysMenu && sysMenu.size() > 0) {
            return new Response(200, "查询成功", sysMenu.get(0));
        } else {
            return new Response(500, "查询失败");
        }
    }

    /**
     * 修改权限菜单
     *
     * @param sysMenu
     * @return
     */
    @ApiOperation(value = "编辑菜单", notes = "编辑菜单")
    @ApiImplicitParam(name = "sysMenu", value = "菜单对象", required = true, dataType = "SysMenu")
    @RequestMapping(value = "/updateMenu", method = RequestMethod.POST)
    public Response updateMenu(@Valid @RequestBody SysMenu sysMenu) {
        List<SysMenu> sysMenus = sysMenuService.getSysMenu(sysMenu.getId(), null, null, null, null);

        //判断菜单名称是否已存在
        if(!sysMenus.get(0).getName().equals(sysMenu.getName())){
            List<SysMenu> name = sysMenuService.getSysMenu(null, sysMenu.getName(), null, null, null);
            //菜单名称已存在,添加失败
            if (null != name && name.size() > 0) {
                return new Response(500, "菜单名称已存在");
            }
        }
//        if(!sysMenus.get(0).getCode().equals(sysMenu.getCode())){
//            //判断菜单编码是否已存在
//            List<SysMenu> code = sysMenuService.getSysMenu(null, null, sysMenu.getCode(), null, null);
//            //编码已存在,添加失败
//            if (null != code && code.size() > 0) {
//                return new Response(500, "编码已存在");
//            }
//        }

        int updateMenu = sysMenuService.updateSysMenu(sysMenu);
        if (updateMenu > 0) {
            //删除redis菜单缓存
//            redisService.remove(RedisConstant.menu);
//            return new Response();
            return new Response(200, "编辑菜单成功");
        } else {
            return new Response(500, "编辑菜单失败");
        }
    }

    /**
     * 菜单管理之是否可见
     *
     * @param sysMenu
     * @return
     */
    @ApiOperation(value = "菜单管理之是否可见", notes = "菜单管理之是否可见")
    @ApiImplicitParam(name = "sysMenu", value = "菜单对象", required = true, dataType = "SysMenu")
    @RequestMapping(value = "/updateMenuKeepAlive", method = RequestMethod.POST)
    public Response updateMenuKeepAlive(@RequestBody SysMenu sysMenu) {
        int i = sysMenuService.setKeepAlive(sysMenu.getId(), sysMenu.getKeepAlive());
        if (i > 0) {
            //清理redis菜单缓存
//            redisService.delLike(RedisConstant.menu);
//            return new Response();
            return new Response(200, "菜单是在是否可见成功");
        } else {
            return new Response(500, "菜单是在是否可见失败");
        }
    }

    /**
     * 菜单管理之权限项查看
     *
     * @param sysMenu
     * @return
     */
    @ApiOperation(value = "菜单管理之权限项查看", notes = "菜单管理之权限项查看")
    @ApiImplicitParam(name = "sysMenu", value = "菜单对象", required = true, dataType = "SysMenu")
    @RequestMapping(value = "/getUserByMenuId", method = RequestMethod.POST)
    public Response getUserByMenuId(@RequestBody SysMenu sysMenu) {
        //1.从用户菜单表查询匹配用户（sys_user_menu）
        //2.从角色菜单表查询匹配用户（sys_role_menu）
        List<SysUser> usersByMenuId = sysUserService.getUsersByMenuId(sysMenu.getId());
        return new Response(200, "查询成功", usersByMenuId);
    }

    @ApiOperation(value = "角色管理之查询用户管理绑定数据")
//    @ApiImplicitParam(name = "roleId", value = "角色Id", required = true, dataType = "Integer", paramType = "query")
    @PostMapping("/getRoleUsers")
    public Map<String, Object> getRoleUsers(@RequestParam("roleId") String roleId) {
        Map<String, Object> map = new HashMap<>();
        //查询角色对应的用户信息
        List<String> userd = sysUserRoleService.getUserIdByRoleId(roleId);
        //查询角色对应的部门信息
        Map<String, Object> condition = new HashMap<>();
        condition.put("role_id", roleId);
        condition.put("delete_flag", 0);

        map.put("userIds", userd);
        return map;
    }

    @ApiOperation(value = "查询用户对应的菜单")
    @GetMapping("/getUserMenuByUserId")
    public Response getUserMenuByUserId(@RequestHeader("userId") String userId){
        return sysMenuService.getSysMenuByUserId(userId);
    }

    @ApiOperation("通过菜单主键获取是否有按钮权限")
    @GetMapping("/getButtonsByMenuId")
    public ResultObject getButtonsByMenuId(@RequestParam("menuId") String menuId) {
        return ResultObject.successReturn(sysMenuService.getButtonsByMenuId(menuId));
    }

    @ApiOperation("获取所有菜单包括按钮")
    @GetMapping("/getAllMenuIncludeButton")
    public ResultObject getAllMenuIncludeButton() {
        return ResultObject.successReturn(sysMenuService.getAllSysMenuTree());
    }
    /**
     * 是否存在权限菜单
     *
     * @param name
     * @return
     */
    @RequestMapping("/isExistMenu")
    public int isExistMenu(@RequestParam("name") String name) {
        List<SysMenu> sysMenu = sysMenuService.getSysMenu(null, name, null, null, null);
        //已存在
        if (null != sysMenu && sysMenu.size() > 0) {
            return Constants.fail;
        } else {
            return Constants.success;
        }
    }
}

